﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

// MobiLib, Copyright Mirosław M. Mączka.  All Rights Reserved. This code released under the terms of the Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

namespace MobiLibrary
{
    public partial class MobiLib
    {
        //==================================================================================================================================
        public class MOBI_header:IMobiHeader
        {
            public bool IsDirty{get; internal set;}
            internal MemoryBlock mb;
            public MemoryBlock MB { get { return mb; } }
            //
            public string Identifier { get { return Bytes2String(mb.Buffer, 0, 4); } }
            public int HeaderLength { get { return Bytes2Int(mb.Buffer, 4); } }
            public int MobiType { get { return Bytes2Int(mb.Buffer, 8); } }
            public string sMobiType { get { return MT.MobiType2String(MobiType); } }
            public int TextEncoding { get { return Bytes2Int(mb.Buffer, 12); } internal set { Int2Bytes(value, mb.Buffer, 12); } }
            public string sTextEncoding { get { return CCP.ToText(Bytes2Int(mb.Buffer, 12)); } }
            public int UniqueID { get { return Bytes2Int(mb.Buffer, 16); } }
            public int FileVersion { get { return Bytes2Int(mb.Buffer, 20); } }
            public int OrtographicIndex { get { return Bytes2Int(mb.Buffer, 24); } }
            public int InflectionIndex { get { return Bytes2Int(mb.Buffer, 28); } }
            public int IndexNames { get { return Bytes2Int(mb.Buffer, 32); } }
            public int IndexKeys { get { return Bytes2Int(mb.Buffer, 36); } }
            public int ExtraIndex0 { get { return Bytes2Int(mb.Buffer, 40); } }
            public int ExtraIndex1 { get { return Bytes2Int(mb.Buffer, 44); } }
            public int ExtraIndex2 { get { return Bytes2Int(mb.Buffer, 48); } }
            public int ExtraIndex3 { get { return Bytes2Int(mb.Buffer, 52); } }
            public int ExtraIndex4 { get { return Bytes2Int(mb.Buffer, 56); } }
            public int ExtraIndex5 { get { return Bytes2Int(mb.Buffer, 60); } }
            public int FirstNonbookIndex { get { return Bytes2Int(mb.Buffer, 64); } }
            public int FullNameOffset { get { return Bytes2Int(mb.Buffer, 68); } internal set { Int2Bytes(value, mb.Buffer, 68); } }
            public int FullNameLength { get { return Bytes2Int(mb.Buffer, 72); } internal set { Int2Bytes(value, mb.Buffer, 72); } }
            public int Locale { get { return Bytes2Int(mb.Buffer, 76); } internal set { Int2Bytes(value, mb.Buffer, 76); } }
            public string sLocale { get { return LanguageCodes.ToText(Bytes2Int(mb.Buffer, 76)); } }
            public int InputLanguage { get { return Bytes2Int(mb.Buffer, 80); ;} internal set { Int2Bytes(value, mb.Buffer, 80); } }
            public string sInputLanguage { get { return LanguageCodes.ToText(Bytes2Int(mb.Buffer, 80)); } }
            public int OutputLanguage { get { return Bytes2Int(mb.Buffer, 84); } internal set { Int2Bytes(value, mb.Buffer, 84); } }
            public string sOutputLanguage { get { return LanguageCodes.ToText(Bytes2Int(mb.Buffer, 84)); } }
            public int MinVersion { get { return Bytes2Int(mb.Buffer, 88); } }
            public int FirstImageindex { get { return Bytes2Int(mb.Buffer, 92); } }
            public int HuffmanRecordOffset { get { return Bytes2Int(mb.Buffer, 96); } }
            public int HuffmanRecordCount { get { return Bytes2Int(mb.Buffer, 100); } }
            public int HuffmanTableOffset { get { return Bytes2Int(mb.Buffer, 104); } }
            public int HuffmanTableLength { get { return Bytes2Int(mb.Buffer, 108); } }
            public int ExthFlags { get { return Bytes2Int(mb.Buffer, 112); } }
            public bool isExth { get { return 0 != (0x40 & Bytes2Int(mb.Buffer, 112)); } }
            //
            public int DrmOffset { get { return Bytes2Int(mb.Buffer, 148); } }
            public int DrmCount { get { return Bytes2Int(mb.Buffer, 152); } }
            public int DrmSize { get { return Bytes2Int(mb.Buffer, 156); } }
            public int DrmFlags { get { return Bytes2Int(mb.Buffer, 160); } }
            //
            public MOBI_header(byte[] buff)
            {
                lock (olock)
                {
                    IsDirty = false;
                    mb.Buffer = new byte[buff.Length]; Array.Copy(buff, 0, mb.Buffer, 0, buff.Length);
                    //
                    // to end
                    if ((buff.Length - 164) <= 0)// invalid file
                    {
                        throw new FormatException("MOBI");
                    }
                }
            }
            //
            //
            internal void Store(MemoryBlock MetaBuffer)
            {
                lock (olock)
                {
                    Array.Copy(mb.Buffer, 0, MetaBuffer.Buffer, mb.Offset, mb.Length);
                }
            }
            //
            //
            public override string ToString()
            {
                lock (olock)
                {
                    string s = "MOBI_header:\n";
                    s += string.Format("MobiType={0}\n", sMobiType);
                    s += string.Format("TextEncoding={0}\n", sTextEncoding);
                    s += string.Format("UniqueID={0}\n", UniqueID);
                    s += string.Format("FileVersion={0}\n", FileVersion);
                    s += string.Format("Locale={0},InputLanguage={1},OutputLanguage={2}\n", sLocale, sInputLanguage, sOutputLanguage);
                    s += string.Format("MinVersion={0}\n", MinVersion);
                    s += string.Format("ExthFlags={0},isExth={1}\n", ExthFlags, isExth);
                    return s;
                }
            }
            //
            public string Dump()
            {
                lock (olock)
                {
                    string s = "MOBI_header: MB=" + mb.ToString() + "\n";
                    s += string.Format("Identifier={0},HeaderLength={1}\n", Identifier, HeaderLength);
                    s += string.Format("MobiType={0}\n", sMobiType);
                    s += string.Format("TextEncoding={0}\n", sTextEncoding);
                    s += string.Format("UniqueID={0}\n", UniqueID);
                    s += string.Format("FileVersion={0}\n", FileVersion);
                    s += string.Format("OrtographicIndex={0},InflectionIndex={1}\n", OrtographicIndex, InflectionIndex);
                    s += string.Format("IndexNames={0},IndexKeys={1}\n", IndexNames, IndexKeys);
                    s += string.Format("ExtraIndex0={0},ExtraIndex1={1},ExtraIndex2={2},ExtraIndex3={3},ExtraIndex4={4},ExtraIndex5={5}\n", ExtraIndex0, ExtraIndex1, ExtraIndex2, ExtraIndex3, ExtraIndex4, ExtraIndex5);
                    s += string.Format("FirstNonbookIndex={0}\n", FirstNonbookIndex);
                    s += string.Format("FullNameOffset={0},FullNameLength={1}\n", FullNameOffset, FullNameLength);
                    s += string.Format("Locale={0},InputLanguage={1},OutputLanguage={2}\n", sLocale, sInputLanguage, sOutputLanguage);
                    s += string.Format("MinVersion={0}\n", MinVersion);
                    s += string.Format("FirstImageindex={0}\n", FirstImageindex);
                    s += string.Format("HuffmanRecordOffset={0},HuffmanRecordCount={1},HuffmanTableOffset={2},HuffmanTableLength={3}\n", HuffmanRecordOffset, HuffmanRecordCount, HuffmanTableOffset, HuffmanTableLength);
                    s += string.Format("ExthFlags={0},isExth={1}\n", ExthFlags, isExth);
                    s += string.Format("DrmOffset={0},DrmCount={1},DrmSize={2},DrmFlags={3}\n", DrmOffset, DrmCount, DrmSize, DrmFlags);
                    return s;
                }
            }
        }
        //
        //==================================================================================================================================
        //
    }//class
}//namespace
